﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using PriceLibrary.PriceService;

using VDataAdapter.BlockingQueue;
using VDataAdapter.PriceServerAdapter;
using VDataAdapter.Utilities;

namespace VDataAdapter.EventManagement
{    
    /// <summary>
    /// This EventSimulator can catch & play back events:
    /// PriceCallBack
    /// ChartCallBack
    /// 
    /// 
    /// </summary>
    public class EventManager
    {
        protected List<Event> _events = new List<Event>();

        public EventManager() { }

        public void AddFirstTimeEvent(IDictionary<string, PriceLibrary.PriceService.StockBase> baseprices, IDictionary<string, PriceLibrary.PriceService.StockBase> top3Prices)
        {
            FirstTimeEvent firstTimeEvent = new FirstTimeEvent(baseprices, top3Prices);
            _events.Add(firstTimeEvent);
        }

        public void AddTransactionsEvent(IList<PriceLibrary.ChartService.Transaction> transactionsList, int countNumber, int totalCountNumber)
        {
            TransactionsEvent transEvent = new TransactionsEvent(transactionsList, countNumber, totalCountNumber, DateTime.Now);             
            _events.Add(transEvent);
        }

        /// <summary>
        /// Event 3 top prices update
        /// </summary>
        /// <param name="top3Prices"></param>
        public void AddTop3PricesEvent(IDictionary<string, PriceLibrary.PriceService.StockBase> top3Prices)
        {
            Top3PricesEvent top3event = new Top3PricesEvent(top3Prices, DateTime.Now);           
            _events.Add(top3event);
        }
        
        //_PriceCallBack.EndReceivedNewTickers += NewTickersReceived;
        
        //_PriceCallBack.MarketInfoChanged += MarketInfo_Changed;
        public void AddMarketInfoChangedEvent(IDictionary<int, PriceLibrary.PriceService.StockBase> marketInfos)
        {    
            MarketInfosEvent ev = new MarketInfosEvent(TypeConvertor.StockBaseToMarketInfo(marketInfos));       
            _events.Add(ev);     
        }

        public void AddPutThroughChangedEvent(IList<PriceLibrary.PriceService.StockBase> newstockbase)
        {   
            var list = new List<PriceLibrary.PriceService.StockInfoDyns>();

            foreach (PriceLibrary.PriceService.StockBase stock in newstockbase)
            {
                list.Add((PriceLibrary.PriceService.StockInfoDyns)stock);
            }

            PtTopPricesChangedEvent ev = new PtTopPricesChangedEvent(list);
         
            _events.Add(ev);
        }

        public void AddPutThroughTransactionEvent(IList<PriceLibrary.PriceService.StockBase> newstockbase)
        {
            var list = new List<PriceLibrary.PriceService.Transaction>();

            foreach (PriceLibrary.PriceService.StockBase stock in list)
            {
                list.Add((PriceLibrary.PriceService.Transaction)stock);
            }
            PtTransactionsChangedEvent ev = new PtTransactionsChangedEvent(list);   
             
            _events.Add(ev);
        }


        //_PriceCallBack.EndReceivedPtTopPrices += PtTopPrices_Changed;
        //_PriceCallBack.EndReceivedPtTransactions += PtTransactions_Changed;

        public static void PlayEvents(IList<Event> events, IPriceServiceHandler eventHandler, int interval)
        {
            foreach (Event eventItem in events)
            {
                System.Threading.Thread.Sleep(interval);
                Type eventType = eventItem.GetType();

                PassEventToHandler(eventHandler, eventItem);
            }
        }

        private static void PassEventToHandler(IPriceServiceHandler eventHandler, Event eventItem)
        {
            if (eventItem is FirstTimeEvent)
            {
                var target = (FirstTimeEvent)eventItem;
                var topPrices = Utils.ConvertDictionary<string, StockBase, StockInfoDyns>(target.Top3Prices);
                eventHandler.GetFirstTime(target.Baseprices, topPrices);
            }

            if (eventItem is Top3PricesEvent)
            {
                var target = (Top3PricesEvent)eventItem;
                eventHandler.Top3PricesStock_Changed(Utils.ConvertDictionary<string, StockBase, StockInfoDyns>(target.Top3Prices));
            }

            if (eventItem is TransactionsEvent)
            {
                var target = (TransactionsEvent)eventItem;
                eventHandler.Transactions_Changed(target.TransactionsList, target.CountNumber, target.TotalCountNumber);
            }

            if (eventItem is MarketInfosEvent)
            {
                var target = (MarketInfosEvent)eventItem;
                eventHandler.MarketInfo_Changed(target.MarketInfosList);
            }

            if (eventItem is PtTopPricesChangedEvent)
            {
                var target = (PtTopPricesChangedEvent)eventItem;
                eventHandler.PutThroughTopPrices_Changed(target.PtTopPricesList);
            }

            if (eventItem is PtTransactionsChangedEvent)
            {
                var target = (PtTransactionsChangedEvent)eventItem;
                eventHandler.PutThroughTransactions_Changed(target.Transactions);
            }
        }

        
        /// <summary>
        /// Play events loaded from file in an constant interval
        /// </summary>
        /// <param name="events"></param>
        /// <param name="eventHandler"></param>
        /// <param name="interval"></param>
        public static void PlayEvents(IList<Event> events, IPriceServerEventHandler eventHandler, int interval)
        {
            foreach(Event eventItem in events)
            {
                System.Threading.Thread.Sleep(interval);
                Type eventType = eventItem.GetType();

                EventToHandlerPasser.PassEvent(eventItem, eventHandler);
            }

            
        }

        public void WriteEvents()
        {
            if (_events.Count != 0)
            {
                PriceServerObjectFile writer = new PriceServerObjectFile();
                writer.WriteToFile("events.test", _events.ToArray());
            }
        }

        public static Event[] LoadEvent(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);

            PriceServerObjectFile reader = new PriceServerObjectFile();

            List<Event> result = new List<Event>();

            while (stream.Position < stream.Length)
            {
                Event ev = (Event)reader.ReadFromStream(stream);
                result.Add(ev);
            }

            stream.Close();

            return result.ToArray();
        }

        public static string[] LoadMessageOutput(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);
            List<string> result = new List<string>();

            PriceServerObjectFile reader = new PriceServerObjectFile();
            while (stream.Position < stream.Length)
            {
                result.Add((string)reader.ReadFromStream(stream));
            }

            stream.Close();

            return result.ToArray();
        }
    }
}
